/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.cabinetinfo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
import vip.xiaonuo.auth.core.util.StpClientUtil;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.biz.modular.cabinetdoor.entity.BizCabinetDoor;
import vip.xiaonuo.biz.modular.cabinetdoor.service.BizCabinetDoorService;
import vip.xiaonuo.biz.modular.cabinetinfo.entity.BizCabinetInfo;
import vip.xiaonuo.biz.modular.cabinetinfo.mapper.BizCabinetInfoMapper;
import vip.xiaonuo.biz.modular.cabinetinfo.param.*;
import vip.xiaonuo.biz.modular.cabinetinfo.service.BizCabinetInfoService;
import vip.xiaonuo.biz.modular.cabinetinfo.vo.BizCabinetInfoResp;
import vip.xiaonuo.biz.modular.cabinetinfo.vo.ClientCabinetInfo;
import vip.xiaonuo.biz.modular.cabinetinfo.vo.ClientCabinetInfoResp;
import vip.xiaonuo.biz.modular.cabinetpermission.service.BizCabinetPermissionUtil;
import vip.xiaonuo.biz.modular.cabinettype.entity.BizCabinetType;
import vip.xiaonuo.biz.modular.cabinettype.service.BizCabinetTypeService;
import vip.xiaonuo.biz.modular.relation.entity.BizRelation;
import vip.xiaonuo.biz.modular.relation.enums.BizRelationCategoryEnum;
import vip.xiaonuo.biz.modular.relation.service.BizRelationService;
import vip.xiaonuo.common.exception.CommonException;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 柜子信息Service接口实现类
 *
 * @author kongxm
 * @date 2022/11/12 22:02
 **/
@Service
public class BizCabinetInfoServiceImpl extends ServiceImpl<BizCabinetInfoMapper, BizCabinetInfo> implements BizCabinetInfoService {
    @Resource
    private BizCabinetTypeService bizCabinetTypeService;
    @Resource
    private BizCabinetDoorService bizCabinetDoorService;
    @Resource
    private BizRelationService bizRelationService;
    @Resource
    private BizCabinetPermissionUtil bizCabinetPermissionUtil;

    @PostConstruct
    public void repairPinyin() {
        // for cabinet info
        list(new LambdaQueryWrapper<BizCabinetInfo>().isNull(BizCabinetInfo::getCabinetNamePinyin)).forEach(item -> {
            BizCabinetInfo bizCabinetInfo = new BizCabinetInfo();
            bizCabinetInfo.setId(item.getId());
            bizCabinetInfo.setCabinetNamePinyin(PinyinUtil.getFirstLetter(item.getCabinetName(), ""));
            updateById(bizCabinetInfo);
        });
        // for cabinet door.
        bizCabinetDoorService.list(new LambdaQueryWrapper<BizCabinetDoor>().isNull(BizCabinetDoor::getCabinetDoorNamePinyin)).forEach(item -> {
            BizCabinetDoor bizCabinetDoor = new BizCabinetDoor();
            bizCabinetDoor.setId(item.getId());
            bizCabinetDoor.setCabinetDoorNamePinyin(PinyinUtil.getFirstLetter(item.getCabinetDoorName(), ""));
            bizCabinetDoorService.updateById(bizCabinetDoor);
        });
    }

    @Override
    public Page<BizCabinetInfoResp> page(BizCabinetInfoPageParam param) {
        if (!StpUtil.hasRoleOr("superAdmin", "sysAdmin")) {
            SaBaseLoginUser saBaseLoginUser = StpLoginUserUtil.getLoginUser();
            param.setUserId(saBaseLoginUser.getId());
        }
        return getBaseMapper().page(Page.of(param.getCurrent(), param.getSize()), param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(BizCabinetInfoAddParam param) {
        // 组柜编号：必填，唯一，不可编辑。
        long count = count(new LambdaQueryWrapper<BizCabinetInfo>().eq(BizCabinetInfo::getCabinetCode, param.getCabinetCode()));
        Assert.isTrue(count == 0, "柜子编号{}已存在", param.getCabinetCode());

        BizCabinetInfo bizCabinetInfo = BeanUtil.toBean(param, BizCabinetInfo.class);
        this.save(bizCabinetInfo);
        saveRelations(bizCabinetInfo.getId(), param.getAdminUserIds());

        // generate the cabinet door records according to the selected cabinet type
        if (StringUtils.isEmpty(param.getCabinetTypeId())) return;
        BizCabinetType cabinetType = bizCabinetTypeService.getById(param.getCabinetTypeId());
        if (cabinetType == null) return;
        String[] cabinetDoorIds = cabinetType.getDoorIdArray().split(",");
        String[] cabinetDoorNames = new String[]{"default"};
        if (ObjectUtil.isNotEmpty(cabinetType.getDoorDisplayNameArray())) {
            cabinetDoorNames = cabinetType.getDoorDisplayNameArray().split(",");
        }
        for (int i = 0; i < cabinetType.getNumberOfDoors(); i++) {
            BizCabinetDoor door = new BizCabinetDoor();
            door.setReagentStorageType(param.getReagentStorageType());
            door.setCabinetDoorType(param.getCabinetInfoType());
            door.setCabinetDoorCode(cabinetDoorIds[i]);
            door.setCabinetDoorName(cabinetDoorNames[i]);
            door.setCabinetGroupId(bizCabinetInfo.getCabinetGroupId());
            door.setCabinetInfoId(bizCabinetInfo.getId());
            // handle making an inventory configuration
            // if add the cabinet, there mustn't be a separated configuration
            door.setMakingInventoryUnit(bizCabinetInfo.getMakingInventoryUnit());
            door.setMakingInventoryCycle(bizCabinetInfo.getMakingInventoryCycle());
            if (StringUtils.isNotEmpty(door.getCabinetDoorName())) {
                door.setCabinetDoorNamePinyin(PinyinUtil.getFirstLetter(door.getCabinetDoorName(), ""));
            }
            bizCabinetDoorService.save(door);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(BizCabinetInfoEditParam param) {
        bizCabinetPermissionUtil.hasPermission(null, param.getId(), null);
        // 组柜编号：必填，唯一，不可编辑。
        long count = count(new LambdaQueryWrapper<BizCabinetInfo>()
                .eq(BizCabinetInfo::getCabinetCode, param.getCabinetCode())
                .ne(BizCabinetInfo::getId, param.getId()));
        Assert.isTrue(count == 0, "组柜编号{}已存在", param.getCabinetCode());

        BizCabinetInfo bizCabinetInfo = this.queryEntity(param.getId());
        BeanUtil.copyProperties(param, bizCabinetInfo);
        if (StringUtils.isNotEmpty(bizCabinetInfo.getCabinetName())) {
            bizCabinetInfo.setCabinetNamePinyin(PinyinUtil.getFirstLetter(bizCabinetInfo.getCabinetName(), ""));
        }
        this.updateById(bizCabinetInfo);

        // find all cabinet door list, and update cabinet group id
        bizCabinetDoorService.list(new LambdaQueryWrapper<BizCabinetDoor>().eq(BizCabinetDoor::getCabinetInfoId, bizCabinetInfo.getId()))
                .forEach(item -> {
                    BizCabinetDoor bizCabinetDoor = new BizCabinetDoor();
                    bizCabinetDoor.setId(item.getId());
                    if (StringUtils.isEmpty(bizCabinetDoor.getReagentStorageType())) {
                        bizCabinetDoor.setReagentStorageType(bizCabinetInfo.getReagentStorageType());
                    }
                    bizCabinetDoor.setCabinetGroupId(bizCabinetInfo.getCabinetGroupId() != null ? bizCabinetInfo.getCabinetGroupId() : "");
                    bizCabinetDoorService.updateById(bizCabinetDoor);
                });

        saveRelations(bizCabinetInfo.getId(), param.getAdminUserIds());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<BizCabinetInfoIdParam> param) {
        // 执行删除
        this.removeBatchByIds(CollStreamUtil.toList(param, BizCabinetInfoIdParam::getId));
        param.forEach(item -> {
            bizCabinetPermissionUtil.hasPermission(null, item.getId(), null);
            bizRelationService.remove(new LambdaQueryWrapper<BizRelation>().eq(BizRelation::getObjectId, item.getId()));
        });
    }

    @Override
    public BizCabinetInfo detail(BizCabinetInfoIdParam bizCabinetInfoIdParam) {
        return this.queryEntity(bizCabinetInfoIdParam.getId());
    }

    @Override
    public BizCabinetInfo queryEntity(String id) {
        BizCabinetInfo bizCabinetInfo = this.getById(id);
        if (ObjectUtil.isEmpty(bizCabinetInfo)) {
            throw new CommonException("柜子信息不存在，id值为：{}", id);
        }
        return bizCabinetInfo;
    }

    @Override
    public boolean switchState(String id) {
        Assert.notNull(id, "id不能为空");
        BizCabinetInfo bizCabinetInfo = getById(id);
        Assert.notNull(bizCabinetInfo, "记录不存在");
        BizCabinetInfo updateBean = new BizCabinetInfo();
        updateBean.setId(id);
        updateBean.setState(bizCabinetInfo.getState() == 1 ? 0 : 1);
        return this.updateById(updateBean);
    }

    @Override
    public List<BizCabinetInfo> getList(BizCabinetInfoIdParam bizCabinetInfoIdParam) {
        return this.getBaseMapper().getListByGroupId(bizCabinetInfoIdParam.getGroupId(), bizCabinetInfoIdParam.getCabinetInfoType());
    }

    private void saveRelations(String cabinetInfoId, String adminIds) {
        if (StringUtils.isEmpty(cabinetInfoId)) return;
        if (StringUtils.isNotEmpty(adminIds)) {
            List<String> list = Arrays.stream(adminIds.split(",")).collect(Collectors.toList());
            bizRelationService.saveRelationBatchWithClear(cabinetInfoId, list,
                    BizRelationCategoryEnum.BIZ_RELATION_CABINET_INFO_AND_ADMIN_USER.getValue());
        }
    }


    @Override
    public List<ClientCabinetInfoResp> listCabinetInfoForClientUserPerm(ClientCabinetInfoIdParam param) {
        return this.getBaseMapper().listCabinetInfoForClient(param).stream()
                .map(item -> {
                    ClientCabinetInfoResp resp = new ClientCabinetInfoResp();
                    resp.setId(item.getId());
                    resp.setCabinetName(item.getCabinetName());
                    resp.setCabinetInfoCode(item.getCabinetInfoCode());
                    Integer maxPermDays = item.getMaxPermDays();
                    // 如果柜门没有配置“权限最大天数”，显示组柜的“权限最大天数”。
                    if (maxPermDays == null) maxPermDays = item.getMaxPermDaysCabinetGroup();
                    resp.setMaxPermDays(maxPermDays);
                    return resp;
                }).collect(Collectors.toList());
    }

    @Override
    public List<ClientCabinetInfoResp> listCabinetInfoForClientUserEvent(ClientCabinetInfoIdParam param) {
        String userId = StpClientUtil.getLoginIdAsString();
        param.setUserId(userId);
        return getBaseMapper().listCabinetInfoForClientUserEvent(param);
    }

    @Override
    public List<ClientCabinetInfo> listCabinetInfoByGoodsForClient() {
        return getBaseMapper().listCabinetInfoByGoodsForClient();
    }

    @Override
    public List<BizCabinetInfo> listCabinetInfoByAdminId(String userId, String searchKey, Integer cabinetInfoType,String cabinetGroupId) {
        return getBaseMapper().listCabinetInfoByAdminId(userId, searchKey, cabinetInfoType,cabinetGroupId);
    }
}
